/*
 * Main_User.c
 *
 * Created  : 20 August 2021
 * Modified : 29 August 2021
 * Author   : HWanyusof
 * Version	: 1.1
 */

#include "usbd_cdc_if.h"
#include "string.h"
#include "stm32f4xx_hal.h"
#include "VEML6031X00.h"
#include "VEML6031X00_Prototypes.h"
#include "typedefinition.h"
#include "VEML6031X00_Application_Library.h"
#include "Main_User.h"


//Global Variables

//Switch the I2C Bus number here (Currently only tested with Teensy3.5 with possibility to use multiple i2c channels)
// I2C_Bus = 1 for Wire 1 (Pin 18-SDA, 19-SCL)
// I2C_Bus = 2 for Wire 2 (Pin 37-SCL, 38-SDA)
//Other Arduino family boards-please use I2C_Bus = 1
//Other platforms will not be affected
int I2C_Bus = 1;
unsigned int ALS_Data;
unsigned int IR_Data;
float Resolution;
float Lux;
Byte ALS_IT;
Byte ALS_GAIN;
Byte PD_DIV4;


void INIT_VEML6031X00()
{
	/* Reset Sensor to default value */
	Reset_Sensor();

	/****************************************************************************/
	/****************************Basic  Initialization***************************/
	/*
     *Basic_Initialization_Auto_Mode() uses the most basic steps to turn on the ALS Sensor.
     *Very useful when first working with the sensor.
     *For the more advanced settings, you can use either the Auto_Mode() or AF_Mode()
     */

	//Basic_Initialization_Auto_Mode();
	Normal_Glass();

	/***************************End of Initialization****************************/
    /****************************************************************************/
}

//Print Function
void PRINT_VEML6031X00()
{
	/*
     *If you are using Basic_Initialization_Auto_Mode() to turn on the ALS Sensor,
     *you can use Print_Data_Only() to read the ALS sensor.
     *If you are using more advanced settings like Auto_Mode() or AF_Mode(),
     *you can use all of the print functions :
     *Print_Data_Only() or Print_All().
     */

	/* Print the sensor output */
	//Print_Data_Only();

	#define TRANSMIT_BUFFER_SIZE  128
	char   TransmitBuffer[TRANSMIT_BUFFER_SIZE];
	char   TransmitBuffer2[TRANSMIT_BUFFER_SIZE];

	int Error = 0;


	do
	{
		HAL_Delay(5);

		ALS_Data = VEML6031X00_AGC();

		ALS_IT = VEML6031X00_GET_ALS_IT();
		ALS_GAIN = VEML6031X00_GET_ALS_GAIN();
		PD_DIV4 = VEML6031X00_GET_PD_DIV4();

		Resolution = VEML6031X00_CAL_Resolution(PD_DIV4, ALS_IT, ALS_GAIN);

		//Calculate Lux
		Lux = VEML6031X00_CAL_Lux(Resolution, ALS_Data);

		//Get IR Data
		IR_Data = VEML6031X00_GET_IR_DATA();

		/* Print the sensor output */
		ftoa(Resolution,TransmitBuffer, 6);
		sprintf(TransmitBuffer2,"%s \r\n",TransmitBuffer);
		CDC_Transmit_FS(TransmitBuffer2,strlen(TransmitBuffer2));
		HAL_Delay(5);

		/* Print the sensor output */
		ftoa(Lux,TransmitBuffer, 6);
		sprintf(TransmitBuffer2,"%s \r\n",TransmitBuffer);
		CDC_Transmit_FS(TransmitBuffer2,strlen(TransmitBuffer2));
		HAL_Delay(5);

		/* Print the sensor output */
		sprintf(TransmitBuffer,"%d , ",IR_Data);
		CDC_Transmit_FS(TransmitBuffer,strlen(TransmitBuffer));
		HAL_Delay(5);

		//if(Error !=HAL_OK)
		if (VEML6031X00_GET_ID() != 0x01)
		{
			Error = 1;
			ALS_Data = 0;
		}
		else if (Error == 1)
		{
			Normal_Glass();
			HAL_Delay(50);
			Error = 0;
		}

	}while(true);

}

//Auto/Self-Timed Mode Basic Initialization Function
void Basic_Initialization_Auto_Mode()
{
	//1.) Switch On the IR and ALS Channel
	//Switch On the Bandgap and LDO
	VEML6031X00_SET_SD(VEML6031X00_SD_ON);
	//Enable ALS IR
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

	//2.) Set the ALS internal calibration (OTP Trigger)
	VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

    //Delay needs to be changed depending on the API of the µ-controller
	HAL_Delay(1000);
}

//Initialization Code for the Normal Glass
void Normal_Glass()
{
    //1.) Initialization
    //Switch Off the Bandgap and LDO
    VEML6031X00_SET_SD(VEML6031X00_SD_OFF);
    //Disable ALS IR
    VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_OFF);

    //2.) Setting up ALS IR
    //ALS_CONF0
    //Set the ALS Integration Time
    VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_3_125ms);
    //Enable/Disable Active Force or Auto Mode
    VEML6031X00_SET_ALS_AF(VEML6031X00_ALS_AUTO);
    //Enable/Disable Interrupt
    VEML6031X00_SET_ALS_INT_EN(VEML6031X00_ALS_INT_DIS);

    //ALS_CONF1
    //Set effective PD size of ALS and IR channel
    VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_QUARTER);
    //Set the Analog Gain
    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x0_5);
    //Set the Persistence
    VEML6031X00_SET_PERS(VEML6031X00_ALS_PERS_1);


    //3.) Switch On the IR and ALS Channel
    VEML6031X00_SET_SD(VEML6031X00_SD_ON);
    VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

    //4.) Set the ALS internal calibration (OTP Trigger)
    VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

    HAL_Delay(500);
}

//Initialization Code for the Dark Glass
void Dark_Glass()
{
    //1.) Initialization
    //Switch Off the Bandgap and LDO
    VEML6031X00_SET_SD(VEML6031X00_SD_OFF);
    //Disable ALS IR
    VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_OFF);

    //2.) Setting up ALS IR
    //ALS_CONF0
    //Set the ALS Integration Time
    VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_100ms);
    //Enable/Disable Active Force or Auto Mode
    VEML6031X00_SET_ALS_AF(VEML6031X00_ALS_AUTO);
    //Enable/Disable Interrupt
    VEML6031X00_SET_ALS_INT_EN(VEML6031X00_ALS_INT_DIS);

    //ALS_CONF1
    //Set effective PD size of ALS and IR channel
    VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_FULL);
    //Set the Analog Gain
    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x2);
    //Set the Persistence
    VEML6031X00_SET_PERS(VEML6031X00_ALS_PERS_1);


    //3.) Switch On the IR and ALS Channel
    VEML6031X00_SET_SD(VEML6031X00_SD_ON);
    VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

    //4.) Set the ALS internal calibration (OTP Trigger)
    VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

    HAL_Delay(500);
}

unsigned int VEML6031X00_AGC()
{
    unsigned int ALS_Data_AGC;
    for(;;)
    {
        ALS_Data_AGC = VEML6031X00_GET_ALS_DATA();

        ALS_IT = VEML6031X00_GET_ALS_IT();
        ALS_GAIN = VEML6031X00_GET_ALS_GAIN();
        PD_DIV4 = VEML6031X00_GET_PD_DIV4();

        if(ALS_Data_AGC < 25000)
        {
            if(PD_DIV4 == VEML6031X00_PD_DIV4_QUARTER)
            {
                VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_FULL);
                HAL_Delay(50);
                continue;
            }
            if(PD_DIV4 == VEML6031X00_PD_DIV4_FULL)
            {
                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x0_5)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x0_66);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x0_66)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x1);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x1)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x2);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x2)
                {
                    if(ALS_IT == VEML6031X00_ALS_IT_3_125ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_6_25ms);
                        HAL_Delay(50);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_6_25ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_12_5ms);
                        HAL_Delay(50);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_12_5ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_25ms);
                        HAL_Delay(60);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_25ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_50ms);
                        HAL_Delay(100);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_50ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_100ms);
                        HAL_Delay(200);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_100ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_200ms);
                        HAL_Delay(300);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_200ms)
                    {
                        VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_400ms);
                        HAL_Delay(500);
                        continue;
                    }

                    if(ALS_IT == VEML6031X00_ALS_IT_400ms)
                    {
                    	HAL_Delay(500);
                        break;
                    }
                }
            }
        }

        if((ALS_Data_AGC >= 25000)&&(ALS_Data_AGC <= 55000))
        {
        	HAL_Delay(300);
            break;
        }

        if(ALS_Data_AGC > 55000)
        {

            if(ALS_IT == VEML6031X00_ALS_IT_400ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_200ms);
                HAL_Delay(300);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_200ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_100ms);
                HAL_Delay(200);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_100ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_50ms);
                HAL_Delay(100);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_50ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_25ms);
                HAL_Delay(60);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_25ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_12_5ms);
                HAL_Delay(50);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_12_5ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_6_25ms);
                HAL_Delay(50);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_6_25ms)
            {
                VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_3_125ms);
                HAL_Delay(30);
                continue;
            }

            if(ALS_IT == VEML6031X00_ALS_IT_3_125ms)
            {
                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x2)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x1);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x1)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x0_66);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x0_66)
                {
                    VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x0_5);
                    HAL_Delay(50);
                    continue;
                }

                if(ALS_GAIN == VEML6031X00_ALS_GAIN_x0_5)
                {
                    if(PD_DIV4 == VEML6031X00_PD_DIV4_FULL)
                    {
                        VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_QUARTER);
                        HAL_Delay(50);
                        continue;
                    }
                    if(PD_DIV4 == VEML6031X00_PD_DIV4_FULL)
                    {
                    	HAL_Delay(50);
                        break;
                    }
                 }
            }

        }


    }

    return ALS_Data_AGC;
}

/*

 * Main_User.c
 *
 * Created  : 20 August 2021
 * Modified : 29 August 2021
 * Author   : HWanyusof
 * Version	: 1.1


#include "usbd_cdc_if.h"
#include "string.h"
#include "stm32f4xx_hal.h"
#include "VEML6031X00.h"
#include "VEML6031X00_Prototypes.h"
#include "typedefinition.h"
#include "VEML6031X00_Application_Library.h"
#include "Main_User.h"


//Global Variables

//Switch the I2C Bus number here (Currently only tested with Teensy3.5 with possibility to use multiple i2c channels)
// I2C_Bus = 1 for Wire 1 (Pin 18-SDA, 19-SCL)
// I2C_Bus = 2 for Wire 2 (Pin 37-SCL, 38-SDA)
//Other Arduino family boards-please use I2C_Bus = 1
//Other platforms will not be affected
int I2C_Bus = 2;

void INIT_VEML6031X00()
{
	 Reset Sensor to default value
	Reset_Sensor();

	**************************************************************************
	***************************Basic  Initialization**************************

     *Basic_Initialization_Auto_Mode() uses the most basic steps to turn on the ALS Sensor.
     *Very useful when first working with the sensor.
     *For the more advanced settings, you can use either the Auto_Mode() or AF_Mode()


	Basic_Initialization_Auto_Mode();

	**************************End of Initialization***************************
    **************************************************************************
}

//Print Function
void PRINT_VEML6031X00()
{

     *If you are using Basic_Initialization_Auto_Mode() to turn on the ALS Sensor,
     *you can use Print_Data_Only() to read the ALS sensor.
     *If you are using more advanced settings like Auto_Mode() or AF_Mode(),
     *you can use all of the print functions :
     *Print_Data_Only() or Print_All().


	 Print the sensor output
	Print_Data_Only();

}

//Auto/Self-Timed Mode Basic Initialization Function
void Basic_Initialization_Auto_Mode()
{
	//1.) Switch On the IR and ALS Channel
	//Switch On the Bandgap and LDO
	VEML6031X00_SET_SD(VEML6031X00_SD_ON);
	//Enable ALS IR
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

	//2.) Set the ALS internal calibration (OTP Trigger)
	VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

    //Delay needs to be changed depending on the API of the µ-controller
	HAL_Delay(1000);
}

//AF/Continuous Forced Mode Initialization Function
void AF_Mode()
{
	//1.) Initialization
	//Switch Off the Bandgap and LDO
	VEML6031X00_SET_SD(VEML6031X00_SD_OFF);
	//Disable ALS IR
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_OFF);

	//2.) Setting up ALS IR
	//ALS_CONF0
	//Set the ALS Integration Time
	VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_50ms);
	//Enable/Disable Active Force or Auto Mode
	VEML6031X00_SET_ALS_AF(VEML6031X00_ALS_AF_EN);
	//For AF Mode, Only ALS_AF_DATA_READY is available


	//ALS_CONF1
	//Set effective PD size of ALS and IR channel
	VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_FULL);
	//Set the Analog Gain
	VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x1);
	//Set the Persistence
	VEML6031X00_SET_PERS(VEML6031X00_ALS_PERS_1);

	//ALS_WH
	//Set the ALS Interrupt Higher Threshold
	VEML6031X00_SET_ALS_HighThreshold(5000);

	//ALS_WL
	//Set the ALS Interrupt Lower Threshold
	VEML6031X00_SET_ALS_LowThreshold(3000);

	//3.) Switch On the IR and ALS Channel
	VEML6031X00_SET_SD(VEML6031X00_SD_ON);
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

	//4.) Set the ALS internal calibration (OTP Trigger)
	VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

	//Clear Initial Interrupt
	VEML6031X00_GET_ALS_INT();

	//Delay needs to be changed depending on the API of the µ-controller
    HAL_Delay(1000);
}

//Auto/Self-Timed Mode Initialization Function
void Auto_Mode()
{
	//1.) Initialization
	//Switch Off the Bandgap and LDO
	VEML6031X00_SET_SD(VEML6031X00_SD_OFF);
	//Disable ALS IR
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_OFF);

	//2.) Setting up ALS IR
	//ALS_CONF0
	//Set the ALS Integration Time
	VEML6031X00_SET_ALS_IT(VEML6031X00_ALS_IT_50ms);
	//Enable/Disable Active Force or Auto Mode
	VEML6031X00_SET_ALS_AF(VEML6031X00_ALS_AUTO);
	//Enable/Disable Interrupt
	VEML6031X00_SET_ALS_INT_EN(VEML6031X00_ALS_INT_EN);

	//ALS_CONF1
	//Set effective PD size of ALS and IR channel
	VEML6031X00_SET_PD_DIV4(VEML6031X00_PD_DIV4_FULL);
	//Set the Analog Gain
	VEML6031X00_SET_ALS_GAIN(VEML6031X00_ALS_GAIN_x1);
	//Set the Persistence
	VEML6031X00_SET_PERS(VEML6031X00_ALS_PERS_1);

	//ALS_WH
	//Set the ALS Interrupt Higher Threshold
	VEML6031X00_SET_ALS_HighThreshold(5000);

	//ALS_WL
	//Set the ALS Interrupt Lower Threshold
	VEML6031X00_SET_ALS_LowThreshold(3000);

	//3.) Switch On the IR and ALS Channel
	VEML6031X00_SET_SD(VEML6031X00_SD_ON);
	VEML6031X00_SET_ALS_IR_SD(VEML6031X00_ALS_IR_SD_ON);

	//4.) Set the ALS internal calibration (OTP Trigger)
	VEML6031X00_SET_ALS_CAL(VEML6031X00_ALS_CAL_ON);

	//Clear Initial Interrupt
	VEML6031X00_GET_ALS_INT();

	//Delay needs to be changed depending on the API of the µ-controller
	HAL_Delay(1000);
}
*/

